In Go language development, database operations are a topic that every developer cannot avoid. As a powerful and elegantly designed ORM library, GORM has become the preferred tool for Go developers due to its simple API and rich features. Whether you are a beginner or an experienced developer, mastering GORM's API can significantly enhance your development efficiency!
Today, we will delve into all the core APIs of GORM, taking you from beginner to expert, thoroughly mastering the secrets of GORM!
Why Choose GORM?#
GORM is not just an ORM tool; it is more like a Swiss Army knife for database operations. Here are the core advantages of GORM:
- Simple API Design: Chain calls, clear and readable code.
- Powerful Feature Support: Supports CRUD, transactions, hooks, preloading, and other advanced features.
- Multi-Database Support: Mainstream databases such as MySQL, PostgreSQL, SQLite, SQL Server, etc.
- Active Community: Rich documentation and community support, fast problem resolution.
Next, we will comprehensively analyze GORM's API from four aspects: Initialization, Model Definition, CRUD Operations, and Advanced Features!
1. Initialization and Configuration#
1.1 Connecting to the Database#
GORM supports various databases; here is an example of connecting to MySQL:
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
fmt.Println("Database connected!")
}
1.2 Configuring GORM#
GORM provides rich configuration options, such as log level, table prefix, etc.:
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info), // Set log level
NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_", // Table prefix
},
})
2. Model Definition#
2.1 Defining Models#
GORM uses structs to define models, and each field can specify database constraints through tags:
type User struct {
gorm.Model // Embed gorm.Model, includes ID, CreatedAt, UpdatedAt, DeletedAt
Name string `gorm:"type:varchar(100);not null"`
Age int `gorm:"default:18"`
Email string `gorm:"uniqueIndex"`
}
2.2 Automatic Migration#
GORM can automatically create or update table structures based on models:
db.AutoMigrate(&User{}) // Automatically create users table
3. CRUD Operations#
3.1 Creating Records#
// Create a single record
user := User{Name: "John", Age: 20}
result := db.Create(&user) // Returns *gorm.DB
fmt.Println(user.ID) // Get the inserted primary key
// Batch create
users := []User{{Name: "Alice"}, {Name: "Bob"}}
db.Create(&users)
3.2 Querying Records#
// Query a single record
var user User
db.First(&user, 1) // Query by primary key
db.First(&user, "name = ?", "John") // Conditional query
// Query multiple records
var users []User
db.Find(&users) // Query all records
db.Where("age > ?", 18).Find(&users) // Conditional query
// Query specific fields
db.Select("name", "age").Find(&users)
// Sorting and pagination
db.Order("age desc").Limit(10).Offset(0).Find(&users)
3.3 Updating Records#
// Update a single record
db.Model(&user).Update("Age", 21)
// Update multiple fields
db.Model(&user).Updates(User{Name: "Alice", Age: 22})
// Batch update
db.Model(&User{}).Where("age < ?", 18).Update("age", 20)
3.4 Deleting Records#
// Delete a single record
db.Delete(&user)
// Delete by primary key
db.Delete(&User{}, 1)
// Batch delete
db.Where("age < ?", 18).Delete(&User{})
4. Advanced Features#
4.1 Transaction Handling#
GORM supports manual and automatic transactions:
// Manual transaction
tx := db.Begin()
if err := tx.Create(&User{Name: "John"}).Error; err != nil {
tx.Rollback()
return
}
tx.Commit()
// Automatic transaction
db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&User{Name: "John"}).Error; err != nil {
return err
}
return nil
})
4.2 Hook Functions#
GORM provides model lifecycle hooks that allow you to execute custom logic at specific points in time:
func (u *User) BeforeCreate(tx *gorm.DB) error {
u.CreatedAt = time.Now()
return nil
}
func (u *User) AfterDelete(tx *gorm.DB) error {
fmt.Println("User deleted:", u.ID)
return nil
}
4.3 Preloading (Solving N+1 Query Problem)#
type Order struct {
gorm.Model
UserID uint
User User
}
var orders []Order
db.Preload("User").Find(&orders) // Preload associated User data
4.4 Raw SQL#
GORM supports executing raw SQL statements:
var users []User
db.Raw("SELECT * FROM users WHERE age > ?", 18).Scan(&users)
db.Exec("UPDATE users SET age = ? WHERE name = ?", 20, "John")
5. Relationships#
5.1 One-to-One#
type Profile struct {
gorm.Model
UserID uint
User User
}
type User struct {
gorm.Model
Profile Profile
}
5.2 One-to-Many#
type Order struct {
gorm.Model
UserID uint
User User
}
type User struct {
gorm.Model
Orders []Order
}
5.3 Many-to-Many#
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
Users []User `gorm:"many2many:user_languages;"`
}
6. Other Features#
6.1 Soft Delete#
GORM supports soft delete, where records are not actually deleted but have the DeletedAt field set:
db.Delete(&user) // Soft delete
db.Unscoped().Delete(&user) // Hard delete
6.2 Custom Table Name#
func (User) TableName() string {
return "custom_users"
}
Summary#
GORM's API design is simple yet powerful, covering all aspects of database operations. Whether it's simple CRUD operations or complex relationship queries and transaction handling, GORM can handle it with ease. By mastering these APIs, you can significantly enhance your development efficiency and write more elegant and efficient Go code.
If you have deeper needs for a specific feature, you can refer to the GORM official documentation for more detailed information. I hope this guide helps you thoroughly master GORM and become the ultimate expert in database operations!
Try GORM now and let your Go language development take off! 🚀
Feel free to follow my public account “Full Stack Development ck” for timely updates on original technical articles.